﻿using System;
using System.Collections.Generic;
using System.Linq;
using SD.Infrastructure.DTOBase;
using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.DataDrive.Bussiness.Models.StockContext;
using SlamDunk.MES.DataDrive.Common;
using SlamDunk.MES.DataDrive.Common.Attributes;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.StockContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;

namespace SlamDunk.MES.DataDrive.Bussiness.Importers
{
    /// <summary>
    /// 导入库存
    /// </summary>
    [DataTag(14, "库存数据", "MES库存数据", DataDriveConfig.RealgoalName, DataDriveConfig.RealgoalConnectionStrings)]
    public class ImportStock
    {
        #region # 导入库存单据类 —— void ImportStockOrderClasses()
        /// <summary>
        /// 导入库存单据类
        /// </summary>
        [DataTag("导入库存单据类")]
        public void ImportStockOrderClasses()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();
            StockOrderClass[] stockOrderClasses = ExcelReader.ReadFile<StockOrderClass>(SystemConfig.InitalForStockDataPath, "库存单据类");

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            foreach (StockOrderClass stockOrderClass in stockOrderClasses)
            {
                stockOrderClass.ConverterValue();
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == stockOrderClass.工厂模型编号)?.Id;
                stockOrderContract.CreateStockOrderClass(stockOrderClass.库存单据类编号, stockOrderClass.库存单据类名称, stockOrderClass.DirectionType, stockOrderClass.GenerateBarcode, facilityId, stockOrderClass.描述);
            }
        }
        #endregion

        #region # 导入库存结转记录 —— void ImportStockSettlements()
        /// <summary>
        /// 导入库存结转记录
        /// </summary>
        [DataTag("导入库存结转记录")]
        public void ImportStockSettlements()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IStockManageContract stockManageContract = ResolveMediator.Resolve<IStockManageContract>();

            StockSettlement[] stockSettlements = ExcelReader.ReadFile<StockSettlement>(SystemConfig.InitalForStockDataPath, "库存结转记录");

            #region # 缓存数据

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.EnterpriseInfos == null)
            {
                ImportCacheData.EnterpriseInfos = resourceContract.GetEnterprisesByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            #endregion

            foreach (StockSettlement stockSettlement in stockSettlements)
            {
                stockSettlement.ConverterValue();

                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == stockSettlement.工厂模型编号)?.Id;
                Guid materialId = ImportCacheData.MaterialInfos.Single(x => x.Number == stockSettlement.物料定义编号).Id;
                string storageLocationId = Transformer.GetStorageLocationId(stockSettlement.StorageLocationType, stockSettlement.储存位置编号);

                if (stockSettlement.是否按批次管理)
                {
                    Guid supplierId = ImportCacheData.EnterpriseInfos.Single(x => x.Number == stockSettlement.供应商编号).Id;
                    MaterialLotParam materialLotParam = new MaterialLotParam
                    {
                        materialId = materialId,
                        supplierId = supplierId,
                        productionBatchNo = stockSettlement.生产批号,
                        producedDate = DateTime.Parse(stockSettlement.生产日期),
                        guaranteePeriod = TimeSpan.FromDays(int.Parse(stockSettlement.保质期)),
                        expiredDate = DateTime.Parse(stockSettlement.过期日期),
                        receptionDate = DateTime.Parse(stockSettlement.接收日期),
                        specification = stockSettlement.规格,
                        materialSourceType = stockSettlement.MaterialSourceType
                    };

                    stockManageContract.SettleStock(materialId, null, materialLotParam, stockSettlement.StorageLocationType, storageLocationId, stockSettlement.储存位置名称, stockSettlement.结转日期, stockSettlement.数量, facilityId, stockSettlement.描述);
                }
                else
                {
                    stockManageContract.SettleStock(materialId, null, null, stockSettlement.StorageLocationType, storageLocationId, stockSettlement.储存位置名称, stockSettlement.结转日期, stockSettlement.数量, facilityId, stockSettlement.描述);
                }
            }
        }
        #endregion

        #region # 导入采购入库单 —— void ImportPurchaseStockInorders()
        /// <summary>
        /// 导入采购入库单
        /// </summary>
        [DataTag("导入采购入库单")]
        public void ImportPurchaseStockInorders()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            StockInOrder[] stockInOrders = ExcelReader.ReadFile<StockInOrder>(SystemConfig.InitalForStockDataPath, "采购入库单");
            StockInOrderDetail[] stockInOrderDetails = ExcelReader.ReadFile<StockInOrderDetail>(SystemConfig.InitalForStockDataPath, "采购入库单明细");

            IGrouping<string, StockInOrderDetail>[] stockInOrderDetailGroups = stockInOrderDetails.GroupBy(x => x.入库单编号).ToArray();

            #region # 缓存数据

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.EnterpriseInfos == null)
            {
                ImportCacheData.EnterpriseInfos = resourceContract.GetEnterprisesByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            IDictionary<string, StockOrderClassInfo> stockOrderClasses = stockOrderContract.GetStockOrderClassesByPage(null, null, null, null, 1, int.MaxValue).Datas.ToDictionary(x => x.Number, x => x);

            #endregion

            foreach (StockInOrder stockInOrder in stockInOrders)
            {
                stockInOrder.ConverterValue();

                IGrouping<string, StockInOrderDetail> stockInOrderDetailGroup = stockInOrderDetailGroups.Single(x => x.Key == stockInOrder.入库单编号);

                IList<StockInOrderDetailParam> detailParams = new List<StockInOrderDetailParam>();
                foreach (StockInOrderDetail stockInOrderDetail in stockInOrderDetailGroup)
                {
                    stockInOrderDetail.ConverterValue();

                    Guid materialId = ImportCacheData.MaterialInfos.Single(x => x.Number == stockInOrderDetail.物料定义编号).Id;

                    if (stockInOrderDetail.是否按批次管理)
                    {
                        Guid supplierId = ImportCacheData.EnterpriseInfos.Single(x => x.Number == stockInOrderDetail.供应商编号).Id;
                        MaterialLotParam materialLotParam = new MaterialLotParam
                        {
                            materialId = materialId,
                            supplierId = supplierId,
                            productionBatchNo = stockInOrderDetail.生产批号,
                            producedDate = DateTime.Parse(stockInOrderDetail.生产日期),
                            guaranteePeriod = TimeSpan.FromDays(int.Parse(stockInOrderDetail.保质期)),
                            expiredDate = DateTime.Parse(stockInOrderDetail.过期日期),
                            receptionDate = DateTime.Parse(stockInOrderDetail.接收日期),
                            specification = stockInOrderDetail.规格,
                            materialSourceType = stockInOrderDetail.MaterialSourceType
                        };
                        StockInOrderDetailParam detailParam = new StockInOrderDetailParam
                        {
                            materialId = materialId,
                            materialLotParam = materialLotParam,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                    else
                    {
                        StockInOrderDetailParam detailParam = new StockInOrderDetailParam
                        {
                            materialId = materialId,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                }

                StockOrderClassInfo stockOrderClass = stockOrderClasses[stockInOrder.库存单据类编号];
                string sourceOrderName = null;
                string sourceOrderId = string.IsNullOrWhiteSpace(stockInOrder.源单据类型)
                    ? null
                    : Transformer.GetSourceOrderId(stockInOrder.SourceOrderType, stockInOrder.源单据编号, out sourceOrderName);
                string targetStorageLocationId = Transformer.GetStorageLocationId(stockInOrder.TargetStorageLocationType, stockInOrder.目标储存位置编号);
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == stockInOrder.工厂模型编号)?.Id;

                stockOrderContract.CreateStockInOrder(stockInOrder.入库单编号, stockOrderClass.Id, stockInOrder.SourceOrderType, sourceOrderId, sourceOrderName, stockInOrder.TargetStorageLocationType, targetStorageLocationId, stockInOrder.目标储存位置名称, facilityId, stockInOrder.描述, detailParams);
            }
        }
        #endregion

        #region # 审核采购入库单 —— void CheckPurchaseStockInOrders()
        /// <summary>
        /// 审核采购入库单
        /// </summary>
        [DataTag("审核采购入库单")]
        public void CheckPurchaseStockInOrders()
        {
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            PageModel<StockInOrderInfo> pageModel = stockOrderContract.GetStockInOrdersByPage(null, null, CheckStatus.Unchecked, null, null, null, null, null, null, null, null, 1, int.MaxValue);
            foreach (StockInOrderInfo stockInOrderInfo in pageModel.Datas)
            {
                stockOrderContract.SubmitStockOrder(stockInOrderInfo.Id);
                stockOrderContract.CheckStockOrder(stockInOrderInfo.Id, true, "审核通过");
            }
        }
        #endregion

        #region # 导入领料出库单 —— void ImportFetchStockOutOrders()
        /// <summary>
        /// 导入领料出库单
        /// </summary>
        [DataTag("导入领料出库单")]
        public void ImportFetchStockOutOrders()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IStockManageContract stockManageContract = ResolveMediator.Resolve<IStockManageContract>();
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            StockOutOrder[] stockOutOrders = ExcelReader.ReadFile<StockOutOrder>(SystemConfig.InitalForStockDataPath, "领料出库单");
            StockOutOrderDetail[] stockOutOrderDetails = ExcelReader.ReadFile<StockOutOrderDetail>(SystemConfig.InitalForStockDataPath, "领料出库单明细");

            IGrouping<string, StockOutOrderDetail>[] stockOutOrderDetailGroups = stockOutOrderDetails.GroupBy(x => x.出库单编号).ToArray();

            #region # 缓存数据

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.EnterpriseInfos == null)
            {
                ImportCacheData.EnterpriseInfos = resourceContract.GetEnterprisesByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            IDictionary<string, StockOrderClassInfo> stockOrderClasses = stockOrderContract.GetStockOrderClassesByPage(null, null, null, null, 1, int.MaxValue).Datas.ToDictionary(x => x.Number, x => x);
            MaterialLotInfo[] materialLots = stockManageContract.GetMaterialLotsByPage(null, null, null, null, null, null, null, null,
                null, null, null, 1, int.MaxValue).Datas.ToArray();

            #endregion

            foreach (StockOutOrder stockOutOrder in stockOutOrders)
            {
                stockOutOrder.ConverterValue();

                IGrouping<string, StockOutOrderDetail> stockInOrderDetailGroup = stockOutOrderDetailGroups.Single(x => x.Key == stockOutOrder.出库单编号);

                IList<StockOutOrderDetailParam> detailParams = new List<StockOutOrderDetailParam>();
                foreach (StockOutOrderDetail stockInOrderDetail in stockInOrderDetailGroup)
                {
                    stockInOrderDetail.ConverterValue();

                    Guid materialId = ImportCacheData.MaterialInfos.Single(x => x.Number == stockInOrderDetail.物料定义编号).Id;

                    if (stockInOrderDetail.是否按批次管理)
                    {
                        Guid supplierId = ImportCacheData.EnterpriseInfos.Single(x => x.Number == stockInOrderDetail.供应商编号).Id;
                        Func<MaterialLotInfo, bool> condition =
                            x =>
                                x.MaterialId == materialId &&
                                x.SupplierId == supplierId &&
                                x.ProductionBatchNo == stockInOrderDetail.生产批号 &&
                                x.GuaranteePeriod == TimeSpan.FromDays(int.Parse(stockInOrderDetail.保质期)) &&
                                x.ExpiredDate == DateTime.Parse(stockInOrderDetail.过期日期) &&
                                x.ReceptionDate == DateTime.Parse(stockInOrderDetail.接收日期) &&
                                x.Specification == stockInOrderDetail.规格 &&
                                x.MaterialSourceType == stockInOrderDetail.MaterialSourceType;
                        MaterialLotInfo materialLotInfo = materialLots.Single(condition);

                        StockOutOrderDetailParam detailParam = new StockOutOrderDetailParam
                        {
                            materialId = materialId,
                            materialLotId = materialLotInfo.Id,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                    else
                    {
                        StockOutOrderDetailParam detailParam = new StockOutOrderDetailParam
                        {
                            materialId = materialId,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                }

                StockOrderClassInfo stockOrderClass = stockOrderClasses[stockOutOrder.库存单据类编号];
                string sourceOrderName = null;
                string sourceOrderId = string.IsNullOrWhiteSpace(stockOutOrder.源单据类型)
                    ? null
                    : Transformer.GetSourceOrderId(stockOutOrder.SourceOrderType, stockOutOrder.源单据编号, out sourceOrderName);
                string sourceStorageLocationId = Transformer.GetStorageLocationId(stockOutOrder.SourceStorageLocationType, stockOutOrder.源储存位置编号);
                string targetStorageLocationId = Transformer.GetStorageLocationId(stockOutOrder.TargetStorageLocationType, stockOutOrder.目标储存位置编号);
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == stockOutOrder.工厂模型编号)?.Id;

                stockOrderContract.CreateStockOutOrder(stockOutOrder.出库单编号, stockOrderClass.Id, stockOutOrder.SourceOrderType, sourceOrderId, sourceOrderName, stockOutOrder.SourceStorageLocationType, sourceStorageLocationId, stockOutOrder.源储存位置名称, stockOutOrder.TargetStorageLocationType, targetStorageLocationId, stockOutOrder.目标储存位置名称, facilityId, stockOutOrder.描述, detailParams);
            }
        }
        #endregion

        #region # 审核领料出库单 —— void CheckFetchStockOutOrders()
        /// <summary>
        /// 审核领料出库单
        /// </summary>
        [DataTag("审核领料出库单")]
        public void CheckFetchStockOutOrders()
        {
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            PageModel<StockOutOrderInfo> pageModel = stockOrderContract.GetStockOutOrdersByPage(null, null, CheckStatus.Unchecked, null, null, null, null, null, null, null, null, null, 1, int.MaxValue);
            foreach (StockOutOrderInfo stockOutOrderInfo in pageModel.Datas)
            {
                stockOrderContract.SubmitStockOrder(stockOutOrderInfo.Id);
                stockOrderContract.CheckStockOrder(stockOutOrderInfo.Id, true, "审核通过");
            }
        }
        #endregion

        #region # 导入领料入库单 —— void ImportFetchStockInorders()
        /// <summary>
        /// 导入领料入库单
        /// </summary>
        [DataTag("导入领料入库单")]
        public void ImportFetchStockInorders()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            StockInOrder[] stockInOrders = ExcelReader.ReadFile<StockInOrder>(SystemConfig.InitalForStockDataPath, "领料入库单");
            StockInOrderDetail[] stockInOrderDetails = ExcelReader.ReadFile<StockInOrderDetail>(SystemConfig.InitalForStockDataPath, "领料入库单明细");

            IGrouping<string, StockInOrderDetail>[] stockInOrderDetailGroups = stockInOrderDetails.GroupBy(x => x.入库单编号).ToArray();

            #region # 缓存数据

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.EnterpriseInfos == null)
            {
                ImportCacheData.EnterpriseInfos = resourceContract.GetEnterprisesByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            IDictionary<string, StockOrderClassInfo> stockOrderClasses = stockOrderContract.GetStockOrderClassesByPage(null, null, null, null, 1, int.MaxValue).Datas.ToDictionary(x => x.Number, x => x);

            #endregion

            foreach (StockInOrder stockInOrder in stockInOrders)
            {
                stockInOrder.ConverterValue();

                IGrouping<string, StockInOrderDetail> stockInOrderDetailGroup = stockInOrderDetailGroups.Single(x => x.Key == stockInOrder.入库单编号);

                IList<StockInOrderDetailParam> detailParams = new List<StockInOrderDetailParam>();
                foreach (StockInOrderDetail stockInOrderDetail in stockInOrderDetailGroup)
                {
                    stockInOrderDetail.ConverterValue();

                    Guid materialId = ImportCacheData.MaterialInfos.Single(x => x.Number == stockInOrderDetail.物料定义编号).Id;

                    if (stockInOrderDetail.是否按批次管理)
                    {
                        Guid supplierId = ImportCacheData.EnterpriseInfos.Single(x => x.Number == stockInOrderDetail.供应商编号).Id;
                        MaterialLotParam materialLotParam = new MaterialLotParam
                        {
                            materialId = materialId,
                            supplierId = supplierId,
                            productionBatchNo = stockInOrderDetail.生产批号,
                            producedDate = DateTime.Parse(stockInOrderDetail.生产日期),
                            guaranteePeriod = TimeSpan.FromDays(int.Parse(stockInOrderDetail.保质期)),
                            expiredDate = DateTime.Parse(stockInOrderDetail.过期日期),
                            receptionDate = DateTime.Parse(stockInOrderDetail.接收日期),
                            specification = stockInOrderDetail.规格,
                            materialSourceType = stockInOrderDetail.MaterialSourceType
                        };
                        StockInOrderDetailParam detailParam = new StockInOrderDetailParam
                        {
                            materialId = materialId,
                            materialLotParam = materialLotParam,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                    else
                    {
                        StockInOrderDetailParam detailParam = new StockInOrderDetailParam
                        {
                            materialId = materialId,
                            quantity = stockInOrderDetail.数量,
                            sort = stockInOrderDetail.排序,
                            description = stockInOrderDetail.描述
                        };
                        detailParams.Add(detailParam);
                    }
                }

                StockOrderClassInfo stockOrderClass = stockOrderClasses[stockInOrder.库存单据类编号];
                string sourceOrderName = null;
                string sourceOrderId = string.IsNullOrWhiteSpace(stockInOrder.源单据类型)
                    ? null
                    : Transformer.GetSourceOrderId(stockInOrder.SourceOrderType, stockInOrder.源单据编号, out sourceOrderName);
                string targetStorageLocationId = Transformer.GetStorageLocationId(stockInOrder.TargetStorageLocationType, stockInOrder.目标储存位置编号);
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == stockInOrder.工厂模型编号)?.Id;

                stockOrderContract.CreateStockInOrder(stockInOrder.入库单编号, stockOrderClass.Id, stockInOrder.SourceOrderType, sourceOrderId, sourceOrderName, stockInOrder.TargetStorageLocationType, targetStorageLocationId, stockInOrder.目标储存位置名称, facilityId, stockInOrder.描述, detailParams);
            }
        }
        #endregion

        #region # 审核领料入库单 —— void CheckFetchStockInOrders()
        /// <summary>
        /// 审核领料入库单
        /// </summary>
        [DataTag("审核领料入库单")]
        public void CheckFetchStockInOrders()
        {
            IStockOrderContract stockOrderContract = ResolveMediator.Resolve<IStockOrderContract>();

            PageModel<StockInOrderInfo> pageModel = stockOrderContract.GetStockInOrdersByPage(null, null, CheckStatus.Unchecked, null, null, null, null, null, null, null, null, 1, int.MaxValue);
            foreach (StockInOrderInfo stockInOrderInfo in pageModel.Datas)
            {
                stockOrderContract.SubmitStockOrder(stockInOrderInfo.Id);
                stockOrderContract.CheckStockOrder(stockInOrderInfo.Id, true, "审核通过");
            }
        }
        #endregion
    }
}
